﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RadowCore.Models
{
    /// <summary>
    /// Single rule in the policy, which is consisted of restriction (source, and destination) and an exception(a DNF of CNF of flows)
    /// </summary>
    class Rule
    {
       
        private string m_source;        
       /// <summary>
       /// The source originator of the rule.
       /// </summary>
        public string Source
        {
            get { return m_source; }
            set { m_source = value; }
        }

        private string m_destination;
        /// <summary>
        /// The destination originator of the rule.
        /// </summary>
        public string Destination
        {
            get { return m_destination; }
            set { m_destination = value; }
        }

        private TreeNode m_exception;
        /// <summary>
        /// The exception of the policy rule.
        /// </summary>
        public TreeNode Exception
        {
            get { return m_exception; }
            set { m_exception = value; }
        }

        public String ToText()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(this.Source + " => " + this.Destination+":");
            if (this.Exception.GetType() == typeof(FalseNode))
                sb.Append(" False");
            else
            {
                for (int cnIndex = 0; cnIndex < ((DisjunctNode)Exception).Conjuncts.Count; cnIndex++)
                {
                    ConjunctNode cn = ((DisjunctNode)Exception).Conjuncts[cnIndex];
                    sb.Append(" { ");
                    for (int opIndex = 0; opIndex < cn.Flows.Count; opIndex++)
                    {
                        OpNode op = cn.Flows[opIndex];
                        sb.Append(" ( ");
                        switch (op.OpName)
                        {
                            case "Flow":
                                {
                                    sb.Append(((FlowNode)op).Source + " -> " + ((FlowNode)op).Destination);
                                };
                                break;
                            case "Equals":
                                {
                                    if (((EqualsOp)op).IsRoleType)
                                        sb.Append(this.Source + ".Role should be equal to " + this.Destination + ".Role");
                                    else
                                        sb.Append(this.Source + ".Originator should be equal to " + this.Destination + ".Originator");
                                };
                                break;
                            case "NotEquals":
                                {
                                    if(((NotEqualOp) op).IsRoleType)
                                        sb.Append(this.Source + ".Role should not be equal to " + this.Destination + ".Role");
                                    else
                                        sb.Append(this.Source + ".Originator should not be equal to " + this.Destination + ".Originator");
                                };
                                break;

                            
                        }
                        sb.Append(" ) ");
                        if (opIndex != cn.Flows.Count - 1)
                            sb.Append(" AND ");
                    }
                    sb.Append(" } ");
                    if (cnIndex != ((DisjunctNode)Exception).Conjuncts.Count - 1)
                        sb.Append(" OR ");
                }
            }
            return sb.ToString();
        }
    }
}
